package com.lemon.boot.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.lemon.boot.common.base.BaseServiceImpl;
import com.lemon.boot.common.consts.ApiConst;
import com.lemon.boot.common.enums.WebTypeEnum;
import com.lemon.boot.common.exception.CustomException;
import com.lemon.boot.common.properties.GeneratorConfigProperties;
import com.lemon.boot.common.utils.GeneratorUtil;
import com.lemon.boot.dao.GeneratorTableDAO;
import com.lemon.boot.dto.GeneratorTableDTO;
import com.lemon.boot.po.GeneratorTablePO;
import com.lemon.boot.service.IGeneratorTableService;
import lombok.extern.log4j.Log4j2;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.File;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 业务实现类
 *
 * @author 李猛
 * @since 2024-02-01
 */
@Log4j2
@Service
public class GeneratorTableServiceImpl extends BaseServiceImpl<GeneratorTableDAO, GeneratorTablePO, GeneratorTableDTO> implements IGeneratorTableService {
    @Resource
    private GeneratorConfigProperties generatorConfigProperties;
    @Resource
    private DataSourceProperties dataSourceProperties;

    @Override
    public Map<String, Boolean> getAllTable() {
        //所有的表
        List<String> allTableList = this.baseMapper.getAllTable();

        //已经生成的表
        List<GeneratorTablePO> tableNameList = this.query().select("table_name").list();
        List<String> existTableList = tableNameList.stream().map(GeneratorTablePO::getTableName).collect(Collectors.toList());

        //转换成map并排序
        return allTableList.stream()
                .collect(Collectors.toMap(i -> i, existTableList::contains))
                .entrySet()
                .stream()
                .sorted(Map.Entry.comparingByValue())
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
    }

    @Override
    @Transactional
    public String add(GeneratorTablePO generatorTablePO) {
        if (!StringUtils.hasText(generatorTablePO.getTableName())) {
            return "请选择要生成的表";
        }

        //1.表名
        String tableName = generatorTablePO.getTableName();
        boolean exists = this.query().eq("table_name", tableName).last("limit 1").exists();
        if (exists) {
            return String.format("\"%s\"已生成，请先删除！", tableName);
        }

        //2.文件名
        if (StringUtils.hasText(generatorTablePO.getTablePrefix())) {
            if (tableName.startsWith(generatorTablePO.getTablePrefix())) {
                tableName = tableName.replace(generatorTablePO.getTablePrefix(), "");
            } else {
                return String.format("表前缀\"%s\"错误！", generatorTablePO.getTablePrefix());
            }
        }

        tableName = StrUtil.toCamelCase(tableName.substring(0, 1).toUpperCase() + tableName.substring(1));

        //3.web页面
        String webPath = String.format("%s%s%s.vue", StringUtils.hasText(generatorTablePO.getWebPath()) ? generatorTablePO.getWebPath() : generatorConfigProperties.getWebPath(), "\\", tableName);

        //4.设置默认值
        generatorTablePO.setAuthor(StringUtils.hasText(generatorTablePO.getAuthor()) ? generatorTablePO.getAuthor() : generatorConfigProperties.getAuthor());
        generatorTablePO.setWebType(StringUtils.hasText(generatorTablePO.getWebType()) ? generatorTablePO.getWebType() : generatorConfigProperties.getWebType());
        generatorTablePO.setFileOverride(generatorTablePO.getFileOverride() != null ? generatorTablePO.getFileOverride() : (generatorConfigProperties.getFileOverride() ? 1 : 0));
        generatorTablePO.setWebPath(webPath);
        generatorTablePO.setFilePath(getGeneratorJavaFileName(tableName));

        //5.向数据库中添加数据
        this.baseMapper.insert(generatorTablePO);

        //6.要生成的web页面
        WebTypeEnum webTypeEnum = Arrays.stream(WebTypeEnum.values()).filter(item -> item.getType().equals(generatorTablePO.getWebType())).findFirst().orElse(WebTypeEnum.COMMON);

        //7.执行生成
        FastAutoGenerator.create(dataSourceProperties.getUrl(), dataSourceProperties.getUsername(), dataSourceProperties.getPassword())
                .globalConfig(GeneratorUtil.globalConfig(generatorTablePO.getAuthor()))//全局配置
                .strategyConfig(GeneratorUtil.strategyConfig(generatorTablePO.getTableName(), generatorTablePO.getTablePrefix()))//策略配置
                .packageConfig(GeneratorUtil.packageConfig())//包配置
                .templateConfig(GeneratorUtil.templateConfig())//模板配置
                .injectionConfig(GeneratorUtil.injectionConfig(webTypeEnum))//注入配置
                .templateEngine(GeneratorUtil.templateEngineConfig(generatorTablePO.getFileOverride() == 1, generatorTablePO.getWebPath()))//模板引擎配置
                .execute();
        return "生成成功！";
    }

    /**
     * 获取Java生成的文件名
     *
     * @param name
     * @return
     */
    private static String getGeneratorJavaFileName(String name) {
        //java文件生成的路径
        String javaPath = String.format("src/main/java/%s", ApiConst.SYSTEM_PACKAGE.replaceAll("\\.", "/"));
        StringBuilder builder = new StringBuilder();
        builder.append(String.format("%s%s%sPO.java", javaPath, "/po/", name));
        builder.append(",");
        builder.append(String.format("%s%s%sDTO.java", javaPath, "/dto/", name));
        builder.append(",");
        builder.append(String.format("%s%s%sDAO.java", javaPath, "/dao/", name));
        builder.append(",");
        builder.append(String.format("%s%s%sController.java", javaPath, "/controller/", name));
        builder.append(",");
        builder.append(String.format("%s%sI%sService.java", javaPath, "/service/", name));
        builder.append(",");
        builder.append(String.format("%s%s%sServiceImpl.java", javaPath, "/service/impl/", name));
        builder.append(",");
        builder.append(String.format("src/main/resources/dao/%sDAO.xml", name));
        return builder.toString();
    }

    @Override
    @Transactional
    public String del(Long id) {
        GeneratorTablePO generatorTablePO = this.baseMapper.selectById(id);

        //1.删除生成的java文件
        String filePath = generatorTablePO.getFilePath();
        if (StringUtils.hasText(filePath)) {
            String[] paths = filePath.split(",");
            for (String path : paths) {
                File file = new File(path);
                boolean deleted = file.delete();
                if (!deleted) {
                    throw new CustomException("文件删除失败！");
                }
            }
        }

        //2.删除web文件
        if (StringUtils.hasText(generatorTablePO.getWebPath())) {
            File file = new File(generatorTablePO.getWebPath());
            boolean deleted = file.delete();
            if (!deleted) {
                throw new CustomException("文件删除失败！");
            }
        }
        return super.del(id);
    }

    @Override
    public Page<GeneratorTablePO> page(GeneratorTableDTO generatorTableDTO) {
        //1.分页信息
        Page<GeneratorTablePO> page = Page.of(generatorTableDTO.getCurrent(), generatorTableDTO.getSize());

        //2.条件构造器
        QueryWrapper<GeneratorTablePO> queryWrapper = new QueryWrapper<GeneratorTablePO>()
                .like(StringUtils.hasText(generatorTableDTO.getTableName()), "table_name", generatorTableDTO.getTableName())
                .like(StringUtils.hasText(generatorTableDTO.getTablePrefix()), "table_prefix", generatorTableDTO.getTablePrefix())
                .like(StringUtils.hasText(generatorTableDTO.getAuthor()), "author", generatorTableDTO.getAuthor())
                .orderByAsc("create_time");

        return this.baseMapper.selectPage(page, queryWrapper);
    }
}